package com.enation.app.javashop.core.payment.plugin.combination;

import com.enation.app.javashop.core.aftersale.model.dos.RefundDO;
import com.enation.app.javashop.core.payment.PaymentErrorCode;
import com.enation.app.javashop.core.payment.model.dos.PaymentBillDO;
import com.enation.app.javashop.core.payment.model.dos.PaymentMethodDO;
import com.enation.app.javashop.core.payment.model.enums.ClientType;
import com.enation.app.javashop.core.payment.model.enums.PaymentPluginEnum;
import com.enation.app.javashop.core.payment.model.enums.TradeType;
import com.enation.app.javashop.core.payment.model.vo.*;
import com.enation.app.javashop.core.payment.service.*;
import com.enation.app.javashop.core.trade.sdk.model.OrderDetailDTO;
import com.enation.app.javashop.framework.exception.ServiceException;
import com.enation.app.javashop.framework.logs.Debugger;
import com.enation.app.javashop.framework.util.CurrencyUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.math.BigDecimal;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author 王志杨
 * @since 2020/10/15 15:22
 * 微信组合钱包支付插件
 */
@Service
public class MergePayPlugin implements PaymentPluginManager {

    @Autowired
    private PaymentManager paymentManager;

    @Autowired
    private Debugger debugger;

    @Autowired
    private PaymentMethodManager paymentMethodManager;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private PaymentBillManager paymentBillManager;

    @Autowired
    private RefundManager refundManager;

    @Autowired
    private RefundItemManager refundItemManager;

    @Override
    public String getPluginId() {
        return PaymentPluginEnum.mergePayPlugin.toString();
    }

    @Override
    public String getPluginName() {
        return PaymentPluginEnum.mergePayPlugin.getDescription();
    }

    @Override
    public List<ClientConfig> definitionClientConfig() {
        return null;
    }

    @Override
    public Form pay(PayBill bill) {
        throw new ServiceException(PaymentErrorCode.E502.code(), "组合支付请调用对应的支付插件支付");
    }

    @Override
    public void onReturn(TradeType tradeType) {

    }

    @Override
    public String onCallback(TradeType tradeType, ClientType clientType) {
        return null;
    }

    @Override
    public String onQuery(PayBill bill) {
        return null;
    }

    @Override
    public boolean onTradeRefund(RefundBill bill) {
        throw new RuntimeException("组合退款请调用退款详情中的退款方法进行退款");
    }

    @Override
    public String queryRefundStatus(RefundBill bill) {
        return null;
    }

    //支持原路退款
    @Override
    public Integer getIsRetrace() {
        return 1;
    }

    @Override
    public PayBill createPaymentBill(PayBill payBill, PaymentMethodDO paymentMethod) {
        //1.强制转换为组合支付帐单实体
        CombinationPayBill combinationPayBill = (CombinationPayBill)payBill;
        if(ObjectUtils.isEmpty(combinationPayBill)){
            throw new RuntimeException("转换异常：转换组合支付帐单实体为空");
        }
        //2.获取两个交易单
        List<PayBill> payBillList = combinationPayBill.getPayBillList();
        if(CollectionUtils.isEmpty(payBillList)){
            throw new RuntimeException("转换异常：转换后的组合支付帐单实体中支付单为空");
        }
        String billIds = "";
        int size = payBillList.size();
        for (int i = 0; i < size; i++) {
            //3. 查询支付方式
            PayBill bill = payBillList.get(i);
            String paymentPluginId = bill.getPluginId();
            PaymentMethodDO itemPaymentMethod = this.paymentMethodManager.getByPluginId(paymentPluginId);
            if (itemPaymentMethod == null) {
                debugger.log("未找到相应的支付方式[" + paymentPluginId + "]");
                throw new ServiceException(PaymentErrorCode.E501.code(), "未找到相应的支付方式[" + paymentPluginId + "]");
            }
            //4.保存支付单
            PaymentBillDO paymentBill = paymentManager.createPaymentBill(bill, itemPaymentMethod);
           //5.准备存入redis的value：payemnt_bill主键id
            Integer billId = paymentBill.getBillId();
            billIds = billIds.concat(billId.toString());
            if(i < size - 1){
                billIds = billIds.concat(",");
            }
        }
        PayBill firstPayBill = payBillList.get(0);
        String key = firstPayBill.getSn() + "_" + this.getPluginId();
        //5.redis中存入，只有组合支付时，将payment_bill存入redis key：order_sn(trade_sn)+paymentPluginId  value:payemnt_bill主键id，1小时为支付此支付单过期
        stringRedisTemplate.opsForValue().set(key, billIds, 3600, TimeUnit.SECONDS);
        for (PayBill bill : payBillList) {
            if (PaymentPluginEnum.weixinPayPlugin.toString().equals(bill.getPluginId())) {
                //返回需要执行的payBill
                return bill;
            }
        }
        return null;
    }

    @Override
    public void createRefundItem(RefundDO refundDO, OrderDetailDTO orderDetail) {
        List<PaymentBillDO> paymentBillList = this.paymentBillManager.getBillListBySnAndTradeType(refundDO.getOrderSn(), orderDetail.getTradeType());
        if (CollectionUtils.isEmpty(paymentBillList)) {
            throw new RuntimeException("申请失败：未找到支付单，无法申请取消订单");
        }
        PaymentBillDO walletPaymentBill = null;
        PaymentBillDO weixinPaymentBill = null;
        for (PaymentBillDO paymentBill : paymentBillList) {
            if (ObjectUtils.isEmpty(paymentBill) && paymentBill.getIsPay() <= 0) {
                throw new RuntimeException("申请失败：未找到支付单，无法申请取消订单");
            }
            if (PaymentPluginEnum.weixinPayPlugin.toString().equals(paymentBill.getPaymentPluginId())) {
                weixinPaymentBill = paymentBill;
            }
            if (PaymentPluginEnum.walletPayPlugin.toString().equals(paymentBill.getPaymentPluginId())) {
                walletPaymentBill = paymentBill;
            }
        }
        if (ObjectUtils.isEmpty(walletPaymentBill) || ObjectUtils.isEmpty(weixinPaymentBill)) {
            throw new RuntimeException("申请失败：未找到支付单，无法申请取消订单");
        }
        //判断已退款金额，具体扣减到那个支付方式中
        Double refundPrice = refundDO.getRefundPrice();
        //获取各支付方式已退款的金额
        Double walletAlreadyRefundPrice = refundItemManager.queryRefundPriceByPluginId(refundDO.getOrderSn(), PaymentPluginEnum.walletPayPlugin.toString());

        //比较钱包支付金额和钱包已退款金额，有可退款金额优先退，不够微信再退
        Double walletTradePrice = walletPaymentBill.getTradePrice();
        //计算钱包可退金额
        Double walletEnableRefundPrice = CurrencyUtil.sub(walletTradePrice, walletAlreadyRefundPrice);
        int compare = BigDecimal.valueOf(walletEnableRefundPrice).compareTo(BigDecimal.valueOf(refundPrice));
        //a.钱包可退的金额大于等于申请退款的金额，只生成钱包退款详情单
        if (compare >= 0) {

            //设置钱包支付金额为申请退款的金额
            walletPaymentBill.setTradePrice(refundPrice);
            refundManager.createRefundItem(refundDO, walletPaymentBill);

        } else {

            //b.钱包可退的金额小于申请退款的金额，且钱包可退金额大于0，钱包退款详情单和微信退款详情单都要生成
            if (walletEnableRefundPrice > 0) {
                //设置钱包支付金额为钱包可退款金额
                walletPaymentBill.setTradePrice(walletEnableRefundPrice);
                refundManager.createRefundItem(refundDO, walletPaymentBill);
            }

            //设置微信支付金额为总申请退款金额减去钱包可退的金额
            weixinPaymentBill.setTradePrice(CurrencyUtil.sub(refundPrice, walletEnableRefundPrice));
            refundManager.createRefundItem(refundDO, weixinPaymentBill);

        }
    }
    
}
